#include "Game.hh"

void Game::setup_rooms(Room* Room1, Room* Room2, Room* Room3, Room* Room4)
{
    //1. Set room exits (bidirectional connections)
    Room1->setExit("north", Room2);
    Room2->setExit("south", Room1);
    Room2->setExit("east", Room3);
    Room2->setExit("north", Room4);
    Room3->setExit("west", Room2);
    Room4->setExit("south", Room2);

    // 2. Place items in the rooms 
    // Hell_Gate: Tears of the undead (+0 attack, +0 defense, +5 health)
    Room1->addItem(new Item("Tears_of_the_undead", "Increases 5 health points", 0, 0, 5));
    // Lava_Crevice: Lava Shield (+0 attack, +2 defense, +0 health)
    Room2->addItem(new Item("Lava_Shield", "Increases 2 defense points", 0, 2, 0));
    // Netherbone_Bridge: Skull Remnant Sword (+2 attack) and Skull Armor (+0 attack, +2 defense)
    Room3->addItem(new Item("Skull_Remnant_Sword", "Increases 2 attack points", 2, 0, 0));
    Room3->addItem(new Item("Skull_Armor", "Increases 2 defense points", 0, 2, 0));

    // 3. Place enemies in the rooms
    Room2->addEnemy(new Lava_Hound());
    Room3->addEnemy(new Bone_King());
    Room4->addEnemy(new Troll()); // Boss enemy
}

void Game::clearScreen()
{
    system(CLEAR);
}

void Game::run(Room* CurrentRoom, Character* player)
{
    bool gameOver = false;
    Room* currentRoom = CurrentRoom;
    Item* randomItem = nullptr;
    while (!gameOver)
    {
        clearScreen();

        // Display current room information and player status
        currentRoom->display();
        cout << "\nYour status: " << player->toString() << "\n\n";

        // Show menu options
        cout << "Choose your action:\n";
        cout << "1. Move (to another room)\n";
        // If the room contains items, show the pick-up option
        if (currentRoom->getItemsString() != "None")
        {
            cout << "2. Pick up item\n";
        }
        // If the room contains enemies, show the attack option
        if (currentRoom->getEnemiesString() != "None")
        {
            cout << "3. Attack enemy\n";
        }
        cout << "4. View inventory\n";
        cout << "5. View status\n";
        cout << "0. Exit game\n";
       
        // Get choice from the user
        int choice = Game::ReadNumber();
       
        switch (choice)
        {
        case 1:
        { 
            randomItem = Game::Move(currentRoom);
            break;
        }
        case 2:
        {
            Pick_up_Item(currentRoom, player);
            break;
        }
        case 3:
        { 
            Attack_Enemy(currentRoom, player, &gameOver);
            break;
        }
        case 4:
        {
            View_Inventory(player);
            break;
        }
        case 5:
        {
            View_Status(player);
            break;
        }
        case 0:
        {
            gameOver = true;
            break;
        }
        default:
        {
            cout << "Invalid option, please try again!\n";
            system("pause");
            break;
        }
        }
        // Check if the player is dead
        if (!player->isAlive())
        {
            cout << "You have died! Game over!\n";
            gameOver = true;
            system("pause");
        }
    }
}

void Game::DeleteAllObjects(Room* Room1, Room* Room2, Room* Room3, Room* Room4, Character* player)
{
    if (Room1 != nullptr)
    {
        delete Room1;
        Room1 = nullptr;
    }

    if (Room2 != nullptr)
    {
        delete Room2;
        Room2 = nullptr;
    }

    if (Room3 != nullptr)
    {
        delete Room3;
        Room3 = nullptr;
    }

    if (Room4 != nullptr)
    {
        delete Room4;
        Room4 = nullptr;
    }

    if (player != nullptr)
    {
        delete player;
        player = nullptr;
    }
}

int Game::ReadNumber()
{
    int choice;
    while (true)
    {
        cout << "Enter option number:";
        cin >> choice;
        if (cin.fail())
        {
            cin.clear();
            cin.ignore(1000, '\n');
            cout << "Invalid input, please try again!\n";
            continue;
        }
        break;
    }
    
    return choice;
}

Item* Game::Move(Room*& currentRoom)
{
    Item* randomItem = nullptr;
    // Move to another room
    cout << "Available directions: " << currentRoom->getExitsString() << "\n";
    cout << "Enter direction (e.g., north, south, east, west):";
    string dir;
    cin >> dir;
    Room* nextRoom = (*currentRoom)[dir]; //operator[] overloaded to return the neighbor room
    if (nextRoom)
    {
        currentRoom = nextRoom;
        //30% chance to drop a random item in the new room
        int randomNum = rand() % 100;
        
        if (randomNum < 30) {
            int itemIndex = rand() % 4;
            switch (itemIndex)
            {
                //This randomItem is deleted in ~Room()
            case 0: randomItem = new Item("Lava_Ring", "Increases 1 attack point", 1, 0, 0); break;
            case 1: randomItem = new Item("Magic_Cloak", "Increases 1 defense point, from previous adventurer", 0, 1, 0); break;
            case 2: randomItem = new Item("Healing_Potion", "Increases 3 health points", 0, 0, 3); break;
            case 3: randomItem = new Item("Hellfire", "Increases 1 attack point", 1, 0, 0); break;
            }
            if (randomItem)
            {
                cout << "On your way, you discover a " << randomItem->name << "!\n";
                cout << randomItem->toString() << "\n";
                currentRoom->addItem(randomItem);
                system("pause");  //*input anykey to continue
            }
        }
    }
    else
    {
        cout << "There is no path in this direction!\n";
        system("pause");
    }
    return randomItem;
}

void Game::Pick_up_Item(Room* currentRoom, Character* player)
{
    if (currentRoom->getItemsString() == "None")
    {
        cout << "Invaid option, there are no items in the room!\n";
        system("pause");
        return;
    }
    // Pick up an item
    cout << "Items available to pick up in the room: " << currentRoom->getItemsString() << "\n";
    cout << "Enter the name of the item you want to pick up:";
    cin.ignore(); // Clear the buffer, avoid mistakes with getline
    string itemName;
    getline(cin, itemName);
    Item* item = currentRoom->takeItem(itemName);
    if (item)
    {
        cout << item->toString() << "\n";
        // Use operator overload to add the item to the player's inventory
        *player += item;
    }
    else
    {
        cout << "Item not found!\n";
    }
    system("pause");
    return;
}

void Game::Attack_Enemy(Room* currentRoom, Character* player, bool* gameOver)
{
    if (currentRoom->getEnemiesString() == "None")
    {
        cout << "Invaid option, there are no enemies in the room!\n";
        system("pause");
        return;
    }
    // Attack an enemy
    cout << "Enemies in the room: " << currentRoom->getEnemiesString() << "\n";
    cout << "Enter the name of the enemy you want to attack:";
    cin.ignore();
    string enemyName;
    getline(cin, enemyName);
    ICharacter* enemy = currentRoom->getEnemy(enemyName);
    if (enemy)
    {
        // Return value true => enemy is dead; false => enemy is alive
        bool enemyDied = (*player) - (*enemy);

        // If the enemy is not dead, they counterattack
        if (!enemyDied)
        {
            // Attempt to cast the enemy to Enemy*, if successful, use special attack
            Enemy* enemyPtr = dynamic_cast<Enemy*>(enemy);
            if (enemyPtr)
            {
                enemyPtr->specialAttack(*player);
            }
        }
        // If the enemy is dead, remove the enemy and check if it is the boss
        else
        {
            cout << enemy->getName() << " is defeated!\n";
            currentRoom->removeEnemy(enemy);
            // Note: Get enemy->getName() before deleting enemy
            if (enemy->getName() == "Troll") {
                cout << "You have defeated the final boss and obtained victory!\n";
                *gameOver = true;
            }
            delete enemy;
            enemy = nullptr;
        }
    }
    else
    {
        cout << "Enemy not found!\n";
    }
    system("pause");
}

void Game::View_Inventory(Character* player)
{
    // View inventory
    player->displayInventory();
    system("pause");
}

void Game::View_Status(Character* player)
{
    // View player status
    player->display();
    system("pause");
}

